#ifndef __SE_EVENT_HANDLER_HPP__
#define __SE_EVENT_HANDLER_HPP__

#include <functional>
#include <vector>
#include <memory>

namespace se {

template <bool> struct _is_return_void { };

/** 事件处理函数类 */
template <typename T> class EventHandler;

template <typename ReturnType, typename ... ArgumentsType>
class EventHandler<ReturnType (ArgumentsType...)> {
    using ElementType = std::function<ReturnType (ArgumentsType...)>;
public:
    /**
     * @brief 增加事件处理函数 / 订阅事件
     * 
     * @param handler 事件处理函数
     * @return EventHandler& 返回事件对象 
     */
    EventHandler &add(const ElementType &handler) {
        this->_handlers.push_back(handler);   
        return *this;
    }

    /**
     * @brief 增加事件处理函数 / 订阅事件
     * 
     * @param handler 事件处理函数
     * @return EventHandler& 返回事件对象 
     */
    EventHandler &add(ElementType &&handler) {
        this->_handlers.push_back(std::move(handler));
        return *this;
    }

    /**
     * @brief 增加事件处理函数 / 订阅事件
     * 
     * @param handler 事件处理函数
     * @return EventHandler& 返回事件对象 
     */
    EventHandler &operator+=(const ElementType &handler) {
        return this->add(handler);
    }

    /**
     * @brief 增加事件处理函数 / 订阅事件
     * 
     * @param handler 事件处理函数
     * @return EventHandler& 返回事件对象 
     */
    EventHandler &operator+=(ElementType &&handler) {
        return this->add(std::move(handler));
    }

    bool empty() const { return this->_handlers.empty(); }

    /**
     * @brief 执行所有的事件处理函数 / 执行所有订阅
     * 
     * @param arguments 事件处理函数的输入
     * @return ReturnType 最后一个事件处理函数的返回值
     */
    template <typename ... InputArguments>
    ReturnType invoke(InputArguments &&... arguments) {
        return this->_invoke(_is_return_void<std::is_void<ReturnType>::value>(), std::forward<InputArguments>(arguments)...);
    }

    /**
     * @brief 执行所有的事件处理函数 / 执行所有订阅
     * 
     * @param arguments 事件处理函数的输入
     * @return ReturnType 最后一个事件处理函数的返回值
     */
    template <typename ... InputArguments>
    ReturnType operator()(InputArguments &&... arguments) {
        return this->invoke(std::forward<InputArguments>(arguments)...);
    }

private:
    /**
     * @brief 执行所有的事件处理函数 / 执行所有订阅
     * 
     * @param _is_return_void
     * @param arguments 
     * @return ReturnType 
     */
    template <typename ... InputArguments>
    ReturnType _invoke(_is_return_void<false>, InputArguments &&... arguments) {
        if (this->empty()) throw "empty event handler list.";
        for (size_t i = 0; i < this->_handlers.size() - 1; ++i) {
            this->_handlers.at(i)(arguments...);
        }
        return this->_handlers.back()(std::forward<InputArguments>(arguments)...);
    }

    /**
     * @brief 执行所有的事件处理函数 / 执行所有订阅
     * 
     * @tparam _is_return_void
     * @param arguments 
     */
    template <typename ... InputArguments>
    void _invoke(_is_return_void<true>, InputArguments &&... arguments) {
        for (auto &element : this->_handlers) {
            element(arguments...);
        }
    }

private:
    std::vector<ElementType> _handlers;
};

}  // namespace se

#endif
